# -*- coding: utf-8 -*-
"""
学习打卡DTO（数据传输对象）
目的：定义学习打卡相关的请求和响应数据结构，提供类型安全和数据验证
职责：封装API请求参数，替代多参数传递，提升代码可维护性
使用场景：Controller层和Service层之间的数据传递
"""
from dataclasses import dataclass
from typing import Optional, List
from datetime import date


@dataclass
class CreateSubjectRequest:
    """
    创建学习科目请求对象
    目的：封装科目创建所需的所有参数，避免方法参数过多
    使用场景：Controller接收到创建科目请求后，将数据封装为此对象传递给Service层
    """
    # 用户ID，从JWT令牌中获取的当前登录用户ID
    user_id: int

    # 科目名称，必填项，如：Python学习、算法练习等
    name: str

    # 科目描述，可选项，详细说明学习内容和目标
    description: Optional[str] = None

    # 科目图标路径，可选项
    icon: Optional[str] = None

    # 科目颜色标识，可选项，默认蓝色
    color: str = '#1890ff'

    # 目标打卡天数，默认0表示无限制
    target_days: int = 0

    # 是否公开，0-私有，1-公开，默认私有
    is_public: int = 0

    # 排序顺序，默认0
    sort_order: int = 0


@dataclass
class UpdateSubjectRequest:
    """
    更新学习科目请求对象
    目的：封装科目更新所需的参数
    使用场景：Controller接收到更新科目请求后，将数据封装为此对象传递给Service层
    """
    # 科目ID，要更新的科目唯一标识
    subject_id: int

    # 用户ID，从JWT令牌中获取，用于验证权限
    user_id: int

    # 以下字段都是可选的，只更新传入的字段
    name: Optional[str] = None
    description: Optional[str] = None
    icon: Optional[str] = None
    color: Optional[str] = None
    target_days: Optional[int] = None
    is_public: Optional[int] = None
    sort_order: Optional[int] = None
    status: Optional[int] = None


@dataclass
class CheckInRequest:
    """
    打卡请求对象
    目的：封装打卡所需的所有参数
    使用场景：Controller接收到打卡请求后，将数据封装为此对象传递给Service层
    """
    # 用户ID，从JWT令牌中获取的当前登录用户ID
    user_id: int

    # 科目ID，必填项，指定打卡的学习科目
    subject_id: int

    # 打卡日期，必填项，格式：YYYY-MM-DD
    check_in_date: date

    # 学习时长（分钟），可选项
    duration_minutes: Optional[int] = None

    # 打卡笔记/学习内容，可选项
    content: Optional[str] = None

    # 学习心情，可选项，1-5的整数
    mood: Optional[int] = None

    # 打卡地点ID，可选项
    location_id: Optional[int] = None

    # 打卡图片路径列表，可选项
    images: Optional[List[str]] = None


@dataclass
class UpdateCheckInRequest:
    """
    更新打卡记录请求对象
    目的：封装更新打卡记录所需的参数
    使用场景：Controller接收到更新打卡请求后，将数据封装为此对象传递给Service层
    """
    # 打卡记录ID，要更新的记录唯一标识
    check_in_id: int

    # 用户ID，从JWT令牌中获取，用于验证权限
    user_id: int

    # 以下字段都是可选的，只更新传入的字段
    duration_minutes: Optional[int] = None
    content: Optional[str] = None
    mood: Optional[int] = None
    location_id: Optional[int] = None
    images: Optional[List[str]] = None


@dataclass
class GetCheckInsListRequest:
    """
    获取打卡记录列表请求对象
    目的：封装打卡记录列表查询的所有筛选和分页参数
    使用场景：Controller接收到列表查询请求后，将查询条件封装为此对象传递给Service层
    """
    # 用户ID，查询指定用户的打卡记录
    user_id: int

    # 页码，从1开始，默认第1页
    page: int = 1

    # 每页显示数量，默认10条，最大100条
    page_size: int = 10

    # 科目ID筛选，None表示不限科目
    subject_id: Optional[int] = None

    # 开始日期筛选，None表示不限
    start_date: Optional[date] = None

    # 结束日期筛选，None表示不限
    end_date: Optional[date] = None

    # 心情筛选，None表示不限
    mood: Optional[int] = None

    # 状态筛选，0-已删除，1-正常，None表示只查正常的
    status: int = 1


@dataclass
class GetStatisticsRequest:
    """
    获取统计数据请求对象
    目的：封装统计查询的参数
    使用场景：Controller接收到统计查询请求后，将查询条件封装为此对象传递给Service层
    """
    # 用户ID，查询指定用户的统计数据
    user_id: int

    # 科目ID筛选，None表示全部科目汇总
    subject_id: Optional[int] = None

    # 开始日期，None表示不限
    start_date: Optional[date] = None

    # 结束日期，None表示不限
    end_date: Optional[date] = None


@dataclass
class GetCalendarRequest:
    """
    获取日历热力图数据请求对象
    目的：封装日历数据查询的参数
    使用场景：用于生成类似GitHub贡献图的打卡日历
    """
    # 用户ID，查询指定用户的打卡日历
    user_id: int

    # 年份，查询指定年份的数据
    year: int

    # 月份，可选项，None表示整年
    month: Optional[int] = None

    # 科目ID筛选，None表示全部科目
    subject_id: Optional[int] = None
